import typing as t

import strawberry
from app.models import User as UserModel
from strawberry.types import Info

from .user import CommunityUser
from .user import DisplayUser


def get_user_by_info(info: Info) -> UserModel:
    return info.context["request"].state.user


@strawberry.type
class UserRelationship:
    @strawberry.field
    async def blocked_user(
        self, info: Info, limit: int = 20, offset: int = 0
    ) -> t.List[DisplayUser]:
        current_user: UserModel = get_user_by_info(info)
        assert limit <= 200
        user_block_list = await (
            current_user.blocked_users.all()
            .limit(limit)
            .offset(offset)
            .only(*DisplayUser.load_model_field(info))
        )
        return user_block_list

    @strawberry.field
    async def blocked_user_count(self, info: Info) -> int:
        current_user: UserModel = get_user_by_info(info)
        return await current_user.blocked_users.all().count()

    @strawberry.field
    async def followees(
        self, info: Info, limit: int = 20, offset: int = 0
    ) -> t.List[CommunityUser]:
        current_user: UserModel = get_user_by_info(info)
        assert limit <= 200
        followees = await (
            current_user.followees.all()
            .limit(limit)
            .offset(offset)
            .only(*DisplayUser.load_model_field(info))
        )
        for followee in followees:
            followee.is_following = True
        return followees

    @strawberry.field
    async def followee_count(self, info: Info) -> int:
        current_user: UserModel = get_user_by_info(info)
        return await current_user.followees.all().count()

    @strawberry.field
    async def followers(
        self, info: Info, limit: int = 20, offset: int = 0
    ) -> t.List[CommunityUser]:
        current_user: UserModel = get_user_by_info(info)

        assert limit <= 200
        followers = await (
            current_user.followers.all()
            .limit(limit)
            .offset(offset)
            .only(*DisplayUser.load_model_field(info))
        )
        followee_id_set = await current_user.get_followee_ids(
            user_id=current_user.auto_id
        )
        for follower in followers:
            follower.is_following = str(follower.auto_id) in followee_id_set
        return followers

    @strawberry.field
    async def follower_count(self, info: Info) -> int:
        current_user: UserModel = get_user_by_info(info)
        return await current_user.followers.all().count()
